﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Xml;

namespace BOMS.Utility.DATA
{
    public class BuildData
    {
        private static int st(int index)
        {
            return index;
        }
        public static bool DataCheck(byte[] buffer)
        {            
            int DataLen = buffer[st(1)] * 16 * 16 + buffer[st(2)];//数据长度
            UInt16 Amt = 0;
            for (int i = 0; i < DataLen; i++)
            {
                Amt += buffer[st(3) + i];//正文数据从第3个字节开始
            }
            return Amt + Convert.ToUInt16(  buffer[st(3 + DataLen)] * 16 * 16 
                                        + buffer[st(3 + DataLen + 1)]
                                        )
                == 65536;

        }
        public static ProtocolPack Converting(byte[] buffer)
        {
            ProtocolPack pack = new ProtocolPack();
            pack.PackHead = "AA";
            pack.PackTail = "55";
            pack.DataLenth = buffer[st(1)] * 16 * 16 + buffer[st(2)];
            pack.Dtm = new DateTime(2000 + buffer[st(3)], buffer[st(4)], buffer[st(5)], buffer[st(6)], buffer[st(7)], buffer[st(8)]);
            pack.GroupCount = buffer[st(9)];
            pack.Arr_BatCount = new int[pack.GroupCount];
            for (int i = 0; i < pack.GroupCount; i++)
            {
                pack.Arr_BatCount[i] = buffer[st(10 + i)];
            }
            pack.RatedCapacity = (buffer[st(15)] * 16 * 16 + buffer[st(16)]) / 100.0; //额定容量
            pack.EnvTemp = ConvertInt16(buffer[st(17)] * 16 * 16 + buffer[st(18)]) / 10.0;
            //电池组
            pack.GroupList = new List<ProtocolGroup>();
            ProtocolGroup group = null;
            int GroupOffset = 0;
            for (int j = 0; j < pack.GroupCount; j++)
            {
                //if (j >= 1)
                //{
                //    GroupOffset = j * 40 + pack.Arr_BatCount[j-1] * 12;
                //}
                GroupOffset = 19 + j * 40 + (j == 0 ? 0 : pack.Arr_BatCount[j - 1]) * 12;//19表示包头长度，40表示组头长度,12表示单体长度
                group = new ProtocolGroup();
                group.GroupNmae = ((char)buffer[st(GroupOffset)]).ToString();
                group.GroupV = (buffer[st(1 + GroupOffset)] * 16 * 16 + buffer[st(2 + GroupOffset)]) / 10.0;
                group.GroupI = ConvertInt16(buffer[st(3 + GroupOffset)] * 16 * 16 + buffer[st(4 + GroupOffset)]) / 10.0;
                group.GroupStatus = buffer[st(5 + GroupOffset)];
                group.GroupStatusDescr = ConvertGroupStatusDescr(group.GroupStatus);//------------------------

                group.GroupError = buffer[st(6 + GroupOffset)];//-------多个状态按位与----------
                group.GroupErrorDescr = ConvertGroupErrorDescr(group.GroupError);
                group.InOutCapacity = (buffer[st(7 + GroupOffset)] * 16 * 16 + buffer[st(8 + GroupOffset)]) / 100.0;
                //group.FullEstiCapacity = (buffer[st(9+GroupOffset)] * 16 * 16 + buffer[st(10+GroupOffset)]) / 100.0;
                ////充放计时
                group.InOutTimeLong = buffer[st(9 + GroupOffset)].ToString("00") + ":" + buffer[st(10 + GroupOffset)].ToString("00");
                group.RemainingCapacity = (buffer[st(11 + GroupOffset)] * 16 * 16 + buffer[st(12 + GroupOffset)]) / 100.0;
                group.RemainingUseTime = buffer[st(13 + GroupOffset)].ToString() + ":" + buffer[st(14 + GroupOffset)].ToString();

                group.VBoundary = new Boundary();
                group.VBoundary.MaxV = (buffer[st(16 + GroupOffset)] * 16 * 16 + buffer[st(17 + GroupOffset)]) / 1000.0;
                group.VBoundary.MaxNO = buffer[st(18 + GroupOffset)].ToString("###");
                group.VBoundary.MinV = (buffer[st(19 + GroupOffset)] * 16 * 16 + buffer[st(20 + GroupOffset)]) / 1000.0;
                group.VBoundary.MinNO = buffer[st(21 + GroupOffset)].ToString("###");

                group.TBoundary = new Boundary();
                group.TBoundary.MaxV = ConvertInt16((buffer[st(24 + GroupOffset)] * 16 * 16 + buffer[st(25 + GroupOffset)])) / 10.0;
                group.TBoundary.MaxNO = buffer[st(26 + GroupOffset)].ToString("###");
                group.TBoundary.MinV = ConvertInt16((buffer[st(27 + GroupOffset)] * 16 * 16 + buffer[st(28 + GroupOffset)])) / 10.0;
                group.TBoundary.MinNO = buffer[st(29 + GroupOffset)].ToString("###");

                group.RBoundary = new Boundary();
                group.RBoundary.MaxV = (buffer[st(32 + GroupOffset)] * 16 * 16 + buffer[st(33 + GroupOffset)]) / 100.0;
                group.RBoundary.MaxNO = buffer[st(34 + GroupOffset)].ToString("###");
                group.RBoundary.MinV = (buffer[st(35 + GroupOffset)] * 16 * 16 + buffer[st(36 + GroupOffset)]) / 100.0;
                group.RBoundary.MinNO = buffer[st(37 + GroupOffset)].ToString("###");

                //单体电池
                group.BattList = new List<ProtocolBattay>();
                int batOffset = 0;
                for (int n = 0; n < pack.Arr_BatCount[j]; n++)
                {
                    batOffset = st(40 + GroupOffset + n * 12);//40表示组头长度,12表示单体长度
                    ProtocolBattay bat = new ProtocolBattay();
                    bat.BattayID = n + 1;
                    bat.BattayStatus =buffer[batOffset+9 ]* 16 * 16 + buffer[batOffset]  ;//状态位由分离的两部分组成（2字节，高位在前）
                    bat.BattayStatusDescr = ConvertBattErrorDescr(bat.BattayStatus);//-------------
                    bat.BattayV = (buffer[batOffset + 1] * 16 * 16 + buffer[batOffset + 2]) / 1000.0;
                    bat.BattayT = ConvertInt16((buffer[batOffset + 3] * 16 * 16 + buffer[batOffset + 4])) / 10.0;
                    bat.BattayR = (buffer[batOffset + 5] * 16 * 16 + buffer[batOffset + 6]) / 100.0;
                    bat.BattayRemainingCapacity = (buffer[batOffset + 7] * 16 * 16 + buffer[batOffset + 8]) / 100.0;

                    group.BattList.Add(bat);
                }
                pack.GroupList.Add(group);
            }
            return pack;
        }
        public static string OutputXML(ProtocolPack pack)
        {
            XmlHelper xh = new XmlHelper("data");
            XmlNode pnode = null;//整体包信息
            XmlNode gnode = null;//组信息
            XmlNode snode = null;//单体信息
            XmlNode bnode = null;//边界值信息

            pnode = xh.AddTextNode("P");
            xh.AddTextNode(pnode, "dtm", pack.Dtm.ToString("yyyy-MM-dd HH:mm:ss"));//现场主机时间
            xh.AddTextNode(pnode, "ent", pack.EnvTemp.ToString());//环境温度
            xh.AddTextNode(pnode, "cd", pack.RatedCapacity.ToString());//额定容量

            for (int j = 0; j < pack.GroupCount; j++)
            {
                gnode = xh.AddTextNode("G");
                xh.AddTextNode(gnode, "g", pack.GroupList[j].GroupNmae);//组名
                xh.AddTextNode(gnode, "v", pack.GroupList[j].GroupV.ToString());//组压
                xh.AddTextNode(gnode, "i", pack.GroupList[j].GroupI.ToString());//组流
                xh.AddTextNode(gnode, "sn", pack.GroupList[j].GroupStatus.ToString());//工作状态编号 
                xh.AddTextNode(gnode, "s", pack.GroupList[j].GroupStatusDescr);//工作状态    
                xh.AddTextNode(gnode, "f", ConvertBattGrpVarningFlag(pack.GroupList[j].GroupError));//警报状态 

                xh.AddTextNode(gnode, "en", pack.GroupList[j].GroupError.ToString());//故障内容编号   
                xh.AddTextNode(gnode, "e", pack.GroupList[j].GroupErrorDescr);//故障内容   

                xh.AddTextNode(gnode, "cd", pack.RatedCapacity.ToString());//额定容量(在包里取的)
                xh.AddTextNode(gnode, "iocp", pack.GroupList[j].InOutCapacity.ToString());//充放容量
                xh.AddTextNode(gnode, "iotl", pack.GroupList[j].InOutTimeLong);//充放计时
                xh.AddTextNode(gnode, "cf", pack.GroupList[j].RemainingCapacity.ToString());//剩余容量
                xh.AddTextNode(gnode, "tf", pack.GroupList[j].RemainingUseTime.ToString());//剩余可用时间

                // --电池组边界值 start-----------------------
                bnode = xh.AddTextNode(gnode, "boundary");
                XmlNode br;
                br = xh.AddTextNode(bnode, "b");
                xh.AddTextNode(br, "type", "v");//电压
                xh.AddTextNode(br, "hv", pack.GroupList[j].VBoundary.MaxV.ToString());//电压最大值
                xh.AddTextNode(br, "hn", pack.GroupList[j].VBoundary.MaxNO);          //电压最大编号
                xh.AddTextNode(br, "lv", pack.GroupList[j].VBoundary.MinV.ToString());//电压最小值
                xh.AddTextNode(br, "ln", pack.GroupList[j].VBoundary.MinNO);          //电压最小编号

                br = xh.AddTextNode(bnode, "b");
                xh.AddTextNode(br, "type", "t");//温度
                xh.AddTextNode(br, "hv", pack.GroupList[j].TBoundary.MaxV.ToString());//温度最大值
                xh.AddTextNode(br, "hn", pack.GroupList[j].TBoundary.MaxNO);          //温度最大编号
                xh.AddTextNode(br, "lv", pack.GroupList[j].TBoundary.MinV.ToString());//温度最小值
                xh.AddTextNode(br, "ln", pack.GroupList[j].TBoundary.MinNO);          //温度最小编号

                br = xh.AddTextNode(bnode, "b");
                xh.AddTextNode(br, "type", "r");//内阻
                xh.AddTextNode(br, "hv", pack.GroupList[j].RBoundary.MaxV.ToString());//内阻最大值
                xh.AddTextNode(br, "hn", pack.GroupList[j].RBoundary.MaxNO);          //内阻最大编号
                xh.AddTextNode(br, "lv", pack.GroupList[j].RBoundary.MinV.ToString());//内阻最小值
                xh.AddTextNode(br, "ln", pack.GroupList[j].RBoundary.MinNO);          //内阻最小编号
                // --池组边界值 end -----------------------

                for (int k = 0; k < pack.GroupList[j].BattList.Count; k++)
                {
                    ProtocolBattay batt = pack.GroupList[j].BattList[k];
                    snode = xh.AddTextNode("r");
                    xh.AddTextNode(snode, "g", pack.GroupList[j].GroupNmae);    //组名
                    xh.AddTextNode(snode, "n", batt.BattayID.ToString());   //电池编号                   
                    xh.AddTextNode(snode, "s", batt.BattayStatusDescr);    //电池状态描述
                    xh.AddTextNode(snode, "sn", batt.BattayStatus.ToString());    //电池状态描述编号
                    xh.AddTextNode(snode, "f", ConvertBattVarningFlag(batt.BattayStatus));    //是否报警

                    xh.AddTextNode(snode, "v", batt.BattayV.ToString());   //电池电压
                    xh.AddTextNode(snode, "t", batt.BattayT.ToString());   //电池温度
                    xh.AddTextNode(snode, "ir", batt.BattayR.ToString());   //电池内阻
                    xh.AddTextNode(snode, "cf", batt.BattayRemainingCapacity.ToString());   //电池剩余容量   
                }
            }
            return xh.ToString();//输出xml文本
        }

        static short ConvertInt16(int n)
        {
            return Convert.ToInt16(n.ToString("X"), 16);
        }
        static string ConvertBattVarningFlag(int BattStatus)
        {
            string flag = "";
            //电池单体状态：0-无故障 1-过压 2-欠压 3-过流 4-过温 5-内阻预警 6-内阻超差 7-内阻超限  8-通讯超时 9-均衡
            if ((BattStatus & 511) > 0) //低9位，任一为1，则有故障
            {
                flag = "1";
            }
            else
            {
                flag = "0";
            }
            return flag;
        }
        static string ConvertBattGrpVarningFlag(int BattStatus)
        {
            string flag = "";
            //bit0-过压 bit1-欠压 bit2-过流 bit3-过温 bit4-内阻预警 bit5-内阻不均 bit6-内阻超限 bit7预留(=1 有该故障; =0 无该故障)
            if ((BattStatus & 127) > 0)// 低7位，任一为1，则有故障
            {
                flag = "1";
            }
            else
            {
                flag = "0";
            }
            return flag;
        }
        static string ConvertGroupStatusDescr(int status)
        {
            if (status == 0)
            {
                return "正常";
            }
            else if (status == 1)
            {
                return "充电";
            }
            else if (status == 2)
            {
                return "核对放电";
            }
            else if (status == 5)
            {
                return "均衡";
            }
            else if (status == 8)
            {
                return "故障";
            }
            return "未知";
        }
        static string ConvertGroupErrorDescr(int status)
        {
            //switch (status)
            //{
            //    case 0:
            //        return "无故障";
            //    case 1:
            //        return "过压";
            //    case 2:
            //        return "欠压";
            //    case 3:
            //        return "过流";
            //    case 4:
            //        return "过温";
            //    case 5:
            //        return "内阻预警";
            //    case 6:
            //        return "内阻不均";
            //    case 7:
            //        return "内阻超限";
            //    default:
            //        return "未知";
            //}
            if (status == 0)
            {
                return "正常";
            }
            else
            {
                BOMS.Utility.GroupErrorStatus grpstatus = (BOMS.Utility.GroupErrorStatus)status;
                return grpstatus.ToString();
            }
        }
        static string ConvertBattErrorDescr(int status)
        {
            //switch (status)
            //{
            //    case 0:
            //        return "无故障";
            //    case 1:
            //        return "过压";
            //    case 2:
            //        return "欠压";
            //    case 3:
            //        return "过流";
            //    case 4:
            //        return "过温";
            //    case 5:
            //        return "内阻预警";
            //    case 6:
            //        return "内阻超差";
            //    case 7:
            //        return "内阻超限";
            //    case 8:
            //        return "内阻异常";
            //    case 9:
            //        return "通讯超时";
            //    case 10:
            //        return "均衡";
            //    default:
            //        return "未知";
            //}
            if (status == 0)
            {
                return "正常";
            }
            else
            {
                BOMS.Utility.BatteryErrorStatus batstatus = (BOMS.Utility.BatteryErrorStatus)status;
                return batstatus.ToString();
            }
        }
    }
}
